package org.example.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
import org.apache.shardingsphere.sharding.algorithm.sharding.mod.ModShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import org.example.datasource.DynamicDataSource;
import org.example.mapper.JkCustomerMapper;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
@EnableTransactionManagement
public class ShardingConfig {
    @Bean("shardingTest")
    @ConfigurationProperties(prefix = "spring.datasource.sharding")
    public DataSource shardingTest() {
        return DruidDataSourceBuilder.create().build();
    }

    @Resource
    private JkCustomerMapper jkCustomerMapper;

    // 定义 ShardingSphere 分表数据源（代理物理 master）
    @Bean("shardingMaster")
    public DataSource shardingMaster(@Qualifier("shardingTest") DataSource shardingTest) throws SQLException {
        // 分表规则配置
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();

        // 1. 定义 t_order 分表规则
        ShardingTableRuleConfiguration orderTableRule = new ShardingTableRuleConfiguration(
                "sharding_jk_customer", // 逻辑表名
                "ds_master.jk_customer_${0..2}" // 实际数据节点（格式: 数据源名.表名）
        );

        // 2. 配置分表策略（精确分片）
        orderTableRule.setTableShardingStrategy(
                new StandardShardingStrategyConfiguration(
                        "customer_id", // 分片列
                        "mod_table" // 分片算法名称（需与后续注册的算法名称一致）
                )
        );
        shardingRuleConfig.getTables().add(orderTableRule);

        // 3. 注册分表算法
        Properties tableAlgorithmProps = new Properties();
        tableAlgorithmProps.setProperty("sharding-count", "2"); // 分2表
        shardingRuleConfig.getShardingAlgorithms().put(
                "mod_table", // 算法名称
                new AlgorithmConfiguration("MOD", tableAlgorithmProps) // 内置 MOD 算法
        );

        // 4. 数据源映射（ShardingSphere 数据源名称 -> 物理数据源）
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("ds_master", shardingTest); // 主库物理数据源

        // 5. 创建 ShardingSphere 数据源
        return ShardingSphereDataSourceFactory.createDataSource(
                dataSourceMap,
                Collections.singleton(shardingRuleConfig), // 分片规则
                new Properties() // 全局属性（可选）
        );
    }

}